/* SPI Master example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "lcd_spi.h"
#include "lvgl.h"
/*
 This code displays some fancy graphics on the 320x240 LCD on an ESP-WROVER_KIT board.
 This example demonstrates the use of both spi_device_transmit as well as
 spi_device_queue_trans/spi_device_get_trans_result and pre-transmit callbacks.

 Some info about the ILI9341/ST7789V: It has an C/D line, which is connected to a GPIO here. It expects this
 line to be low for a command and high for data. We use a pre-transmit callback here to control that
 line: every transaction has as the user-definable argument the needed state of the D/C line and just
 before the transaction is sent, the callback will set this line to the correct state.
*/

void vTask1(void *pvParameters);
void lvgl_template_init();
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);
static void disp_init(void);
void lv_port_disp_init(void);
static lv_disp_draw_buf_t draw_buf_dsc_1;
static lv_color_t buf_1[240 * 10];                          /*A buffer for 10 rows*/
static lv_disp_drv_t disp_drv;                         /*Descriptor of a display driver*/
void systick(void *pvParameters);
void task3(void *pvParameters);
void draw();
void app_main(void)
{
   
    //spi_lcd_init();
    xTaskCreate(vTask1,"vtask1",4096*20,NULL,5,NULL);
    xTaskCreate(systick,"vtask2",4096*30,NULL,6,NULL);
    //xTaskCreate(task3,"vtask3",4096*30,NULL,3,NULL);
}


void vTask1(void *pvParameters)
{
    lv_init();
     lv_port_disp_init();
    while(1)
    {  
        lv_task_handler();
        vTaskDelay(10);
    }
}

void systick(void *pvParameters)
{
    int i = 9;
    while(1)
    {
        lv_tick_inc(1);//lvgl 的 1ms 心跳
        i++;
        if(i == 20 )
        {
           // draw();
        }
        printf("hello");
        vTaskDelay(10);
        
    }
}

void task3(void *pvParameters)
{
    int i = 0;
    while(1)
    {
        i++;
        // if(i == 20)
        // {
        //     draw();
        //     printf("button success");
        // }
        printf("bt");
        vTaskDelay(10);
    }
}

void draw()
{
    lv_obj_t * label;

    lv_obj_t * btn1 = lv_btn_create(lv_scr_act());
    lv_obj_add_event_cb(btn1, NULL, LV_EVENT_ALL, NULL);
    lv_obj_align(btn1, LV_ALIGN_CENTER, 0, -40);

    label = lv_label_create(btn1);
    lv_label_set_text(label, "Button");
    lv_obj_center(label);

    lv_obj_t * btn2 = lv_btn_create(lv_scr_act());
    lv_obj_add_event_cb(btn2, NULL, LV_EVENT_ALL, NULL);
    lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 40);
    lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);
    lv_obj_set_height(btn2, LV_SIZE_CONTENT);

    label = lv_label_create(btn2);
    lv_label_set_text(label, "Toggle");
    lv_obj_center(label);
}

void lv_port_disp_init(void)
{
    /*-------------------------
     * Initialize your display
     * -----------------------*/
    disp_init();

    /*-----------------------------
     * Create a buffer for drawing
     *----------------------------*/

    /**
     * LVGL requires a buffer where it internally draws the widgets.
     * Later this buffer will passed to your display driver's `flush_cb` to copy its content to your display.
     * The buffer has to be greater than 1 display row
     *
     * There are 3 buffering configurations:
     * 1. Create ONE buffer:
     *      LVGL will draw the display's content here and writes it to your display
     *
     * 2. Create TWO buffer:
     *      LVGL will draw the display's content to a buffer and writes it your display.
     *      You should use DMA to write the buffer's content to the display.
     *      It will enable LVGL to draw the next part of the screen to the other buffer while
     *      the data is being sent form the first buffer. It makes rendering and flushing parallel.
     *
     * 3. Double buffering
     *      Set 2 screens sized buffers and set disp_drv.full_refresh = 1.
     *      This way LVGL will always provide the whole rendered screen in `flush_cb`
     *      and you only need to change the frame buffer's address.
     */

    /* Example for 1) */

    lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, 240 * 10);   /*Initialize the display buffer*/

    /*-----------------------------------
     * Register the display in LVGL
     *----------------------------------*/


    lv_disp_drv_init(&disp_drv);                    /*Basic initialization*/

    /*Set up the functions to access to your display*/

    /*Set the resolution of the display*/
    disp_drv.hor_res = 320;
    disp_drv.ver_res = 240;

    /*Used to copy the buffer's content to the display*/
    disp_drv.flush_cb = disp_flush;

    /*Set a display buffer*/
    disp_drv.draw_buf = &draw_buf_dsc_1;

    /*Required for Example 3)*/
    //disp_drv.full_refresh = 1

    /* Fill a memory array with a color if you have GPU.
     * Note that, in lv_conf.h you can enable GPUs that has built-in support in LVGL.
     * But if you have a different GPU you can use with this callback.*/
    //disp_drv.gpu_fill_cb = gpu_fill;

    /*Finally register the driver*/
    lv_disp_drv_register(&disp_drv);
}

static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    LCD_Fill(area->x1,area->y1,area->x2+1,area->y2+1,*(uint16_t*)color_p);
    lv_disp_flush_ready(disp_drv);
}

/*Initialize your display and the required peripherals.*/
static void disp_init(void)
{
    spi_lcd_init();
}